package com.zoe.onelink.common.exception;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.zoe.onelink.common.enumeration.ExceptionCode;
import com.zoe.onelink.common.enumeration.ExceptionCodeEnum;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;

import java.io.Serializable;

/**
 * <p>标题: </p>
 * <p>描述: </p>
 * <p>版权: Copyright (c) 2021</p>
 * <p>公司: 智业软件股份有限公司</p>
 *
 * @version: 1.0
 * @author: ruansheng
 * @date: 2021-07-28
 */
@Getter
@Setter
@Accessors(chain = true)
public class ApiException extends RuntimeException implements Serializable {

    private static final long serialVersionUID = 5183554860342132931L;

    /**
     * 响应编码
     */
    private ExceptionCode exceptionCode;

    /**
     * 占位符参数
     */
    private Object[] params;

    /**
     * 异常详情
     */
    private String error;

    /**
     * 内部缓存格式化后的异常消息
     */
    @JsonIgnore
    private transient String formattedMessage;

    protected ApiException() {
        super();
    }

    private ApiException(String message) {
        super(message);
    }

    private ApiException(Throwable cause) {
        super(cause);
    }

    /**
     * 创建基本异常类
     */
    public static ApiException createEx() {
        return new ApiException().setExceptionCode(ExceptionCodeEnum.BIZ_ERROR);
    }

    /**
     * 根据异常消息、参数列表创建异常
     * 已废弃,兼容旧项目直接字符串抛出异常的方式,后面会移除该方法
     *
     * @param message 消息
     * @param params  参数列表
     */
    @Deprecated
    public static ApiException createEx(String message, Object... params) {
        return new ApiException(message).setParams(params);
    }

    /**
     * 根据传入的异常上下文抛出异常
     *
     * @param cause 异常对象
     */
    public static ApiException createEx(Throwable cause) {
        return new ApiException(cause);
    }

    /**
     * 创建异常
     *
     * @param cause         异常对象
     * @param exceptionCode 异常编码
     * @param params        参数列表
     */
    public static ApiException createEx(Throwable cause, ExceptionCode exceptionCode, Object... params) {
        return new ApiException(cause).setExceptionCode(exceptionCode).setParams(params);
    }


    /**
     * 根据异常编码创建异常
     *
     * @param exceptionCode 异常编码
     */
    public static ApiException createEx(ExceptionCode exceptionCode) {
        return new ApiException().setExceptionCode(exceptionCode);
    }

    /**
     * 根据异常编码、参数列表创建异常
     *
     * @param exceptionCode 异常编码
     * @param params        参数列表
     */
    public static ApiException createEx(ExceptionCode exceptionCode, Object... params) {
        return new ApiException().setExceptionCode(exceptionCode).setParams(params);
    }

    /**
     * 获取异常信息 (需要注意Try catch中的异常信息是否国际化)
     */
    @Override
    public String getMessage() {
        if (this.formattedMessage == null) {
            String message = super.getMessage();
            if (message != null && message.length() > 0) {
                this.formattedMessage = message;
            } else if (exceptionCode != null) {
                this.formattedMessage = exceptionCode.getMessageKey();
            } else {
                this.formattedMessage = message;
            }
        }
        return this.formattedMessage;
    }

}
